package structure;

import java.util.ArrayList;

import utilities.rle2dUtilities;

public class Sequence {
	private ArrayList<Byte> pixels;
	private int curIndex;
	private int seriesLen;
	private byte value;
	private int curSeriesCount;
	private boolean isSeries = false;
	private int MARKER;
	private int rleType;
	private int[] map;
	
	public Sequence(ArrayList<Byte> pixels, int marker)
	{
		this.rleType = rle2dUtilities.CUSTOM_RLE;
		this.pixels = pixels;
		this.MARKER = marker;
	}
	
	public Sequence(ArrayList<Byte> pixels, int[] map)
	{
		this.rleType = rle2dUtilities.PCX_RLE;
		this.pixels = pixels;
		this.map = map;
	}
	
//	public int countCapacity(){
//		int capacity = 0;
//		for (int i=0; i<pixels.size(); i++){
//			Byte val = pixels.get(i);
//			if (val != (byte)MARKER){
//				capacity ++;
//			} else {
//				if(pixels.get(i+1) == rle2dUtilities.H_SERIES_MARKER_COLOR) {
//					capacity ++;
//					i++;
//				} else {
//					Byte len = pixels.get(i+1);
//					capacity += len.intValue() & 0xFF;
//					i++;
//					i++;
//				}
//			}
//		}
//		return capacity;
//	}
	
	public Byte getNextVal(){
		if(this.rleType == rle2dUtilities.CUSTOM_RLE)
			return  getNextValRleCust();
		else
			return getNextValRlePcx();
	}
	
	public Byte getNextValRleCust(){
		Byte ret = null;
		if(!isSeries){
			try {
				ret = pixels.get(curIndex);
			}
			catch(IndexOutOfBoundsException exc) {
				System.out.println("Indeks poza wektorem");
				exc.printStackTrace();
			}
			if(ret == (byte)MARKER) {
				Byte nextVal = pixels.get(curIndex+1);
				if(nextVal == rle2dUtilities.H_SERIES_MARKER_COLOR) {
					curIndex = curIndex+2;
					return ret;
				}
				else {
					isSeries = true;
					seriesLen = nextVal & 0xFF;
					value = pixels.get(curIndex+2);
					if(seriesLen == 1)
						isSeries = false;
					curSeriesCount = 1;
					curIndex = curIndex+3;
					return value;
				}
			}
			else {
				curIndex++;
				return ret;
			}
		}
		else {
			curSeriesCount++;
			if (curSeriesCount >= seriesLen){
				isSeries = false;
				curSeriesCount = 0;
				seriesLen = 0;
			}
			return value;
		}
	}

	
	public Byte getNextValRlePcx(){
		Byte ret = null;
		int val = getOneByteValue(pixels.get(curIndex));
		if(!isSeries) {
			if(val >= rle2dUtilities.RLE_PCX_TRESHOLD) {
				seriesLen = val-rle2dUtilities.RLE_PCX_TRESHOLD;
				if(seriesLen<=1) {
					curIndex++;
					ret = (byte)(getMapValue(getOneByteValue(pixels.get(curIndex))));
					curIndex++;
				} else {
					isSeries = true;
					curIndex++;
					ret = (byte)(getMapValue(getOneByteValue(pixels.get(curIndex))));
					seriesLen--;
				}
			} else {
				ret = (byte)(getMapValue(val));
				curIndex++;
			}
		}
		else {
			ret = (byte)(getMapValue(getOneByteValue(pixels.get(curIndex))));
			if(seriesLen == 1) {
				isSeries = false;
				curIndex++;
			}
			seriesLen--;
		}
		return ret;
	}
	
	public ArrayList<Byte> getPixels() {
		return pixels;
	}
	public void setPixels(ArrayList<Byte> pixels) {
		this.pixels = pixels;
	}
	public int getCurIndex() {
		return curIndex;
	}
	public void setCurIndex(int curIndex) {
		this.curIndex = curIndex;
	}
	public int getSeriesLen() {
		return seriesLen;
	}
	public void setSeriesLen(int seriesLen) {
		this.seriesLen = seriesLen;
	}
	public int getValue() {
		return value;
	}
	public void setValue(byte value) {
		this.value = value;
	}
	public int getCurSeriesCount() {
		return curSeriesCount;
	}
	public void setCurSeriesCount(int curSeriesCount) {
		this.curSeriesCount = curSeriesCount;
	}
	public int getMapValue(int val){
		return map[val];
	}
	
	public int getOneByteValue(byte fst) {
		Byte fstByte = new Byte(fst);
		int fstIntVal = fstByte.intValue() & 0xFF;
		return fstIntVal;
	}
	
}
